package rbm.modelado.problemas;

import java.util.Comparator;
import java.util.SortedSet;

import rbm.modelado.estados.EstadoMochila;
import rbm.modelado.soluciones.SolucionMochila;
import modelado.datos.Datos;
import modelado.datos.elementos.Elemento;
import modelado.datos.elementos.ObjetoMochila;
import modelado.estados.Estado;
import modelado.problemas.*;
import modelado.soluciones.Soluciones;
import modelado.tipos.TipoDeObjetivo;
import utiles.Utiles;

public class ProblemaRBMRyPImpl extends ProblemaRBMImpl implements	ProblemaRyP {
	/**
	 * Constructor
	 * 
	 * @param d
	 *            : datos
	 * @param c
	 *            : capacidad
	 *            
	 *      public ProblemaRBMRyPImpl(Datos d, Integer c) {
		super(d, c);
	}
	 */
	

	/**
	 * Constructor
	 * 
	 * @param c
	 *            : capacidad
	 *            
	 *            public ProblemaRBMRyPImpl(Integer c) {
		super(c);
	}
	 */
	

	public ProblemaRBMRyPImpl(Datos d) {
		super(d);
		// TODO Auto-generated constructor stub
	}


	/**
	 * Se comprueba si cumple las restricciones y si se poda
	 */
	public boolean cumpleRestricciones(Elemento e, Estado es) {
		boolean r = true;
				
		if (r)
			r = funcionDeCota(e, es);

		
		return r;
	}

	
	/**
	 * Funcion de cota
	 * @param e
	 *            : elemento
	 * @param es
	 *            : estado de la mochila
	 */
	public boolean funcionDeCota(Elemento e, Estado es) {
		boolean res = true;
		
		Integer mejorValor;
		double valor, capacidadRestante, unidades;
		
		EstadoMochila esm = (EstadoMochila) es;
		Soluciones sols = esm.getSoluciones();
		ObjetoMochila objMochila;
		// TODO 
		//Primero se comprueba si el tipo de objetivo
		// es la mejor solucion y si ya hay una solucion
		if (this.getTipoDeObjetivo() == TipoDeObjetivo.MEJOR_SOLUCION &&
				sols.haySolucion()) {
			
			// Obtenemos la solucion de la mochila
			SolucionMochila sol = (SolucionMochila) sols.getSolucion();
			
			// Obtenemos el mejor valor de la solucion
			mejorValor = sol.getValor();
			
			// Obtenemos la capacidad restante del estado
			capacidadRestante = esm.getCapacidadRestante();
			
			// Obtenemos el valor del estado
			valor = esm.getValor();
			
			// Recorremos todos los elementos activos del estado
			for (Elemento el:es.getActivos()) {
				
				// Comprobar que el objetoMochila actual no es
				// el objetoMochila pasado por parametro
				objMochila = (ObjetoMochila)el;
				
				if(!objMochila.equals(e)){
					
					// las unidades posibles seran el minimo entre
					// la capacidad restante / peso y
					// el numero maximo de instancias del objeto mochila
					unidades = Math.min(capacidadRestante/objMochila.getPeso(),objMochila.getNumMaxInstancias());					
					
					// El nuevo valor sera el valor anterior mas
					// el valor del obmjeto mochila por las unidades
					valor += objMochila.getValor() * unidades;
					
					// La capacidad restante sera la antigua menos
					// el peso del objeto mochila por las unidades
					capacidadRestante -= objMochila.getPeso() * unidades;
					
					// Si la capacidad restante es 0, salir.
					if(capacidadRestante <= 0)
						break;
				}
			}
			// FALLO SE PODARA SI EL VALOR OBTENIDO ES MENOR!!!! QUE EL DE LA SOLUCION
			// Se podara si el valor obtenido es mayor que el mejor valor de la
			// solucion
			if(valor < mejorValor)
				res = false;
		}
		
		// se incluye las veces que filtra a las metricas
		if(!res) esm.getMetricas().addUnFiltro();
		
		return res;
		
	}

	@Override
	public SortedSet<Elemento> getCandidatos(Estado e) {
		// TODO Auto-generated method stub
		return null;
	}

	@Override
	public Estado getEstadoInicial() {
		// TODO Auto-generated method stub
		return null;
	}

	@Override
	public Comparator<Elemento> getOrden(Estado es) {
		// TODO Auto-generated method stub
		return null;
	}

}
